/****************************************************************************
 *
 * Copyright 2019 NXP Semiconductors All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific
 * language governing permissions and limitations under the License.
 *
 ****************************************************************************/
/****************************************************************************
 * os/arch/arm/src/imxrt/imxrt_gpio.c
 *
 *   Copyright (C) 2018 Gregory Nutt. All rights reserved.
 *   Author: Gregory Nutt <gnutt@nuttx.org>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name NuttX nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/****************************************************************************
 * Included Files
 ****************************************************************************/

#include <tinyara/config.h>

#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>

#include <tinyara/irq.h>

#include "chip.h"
#include "up_arch.h"
#include "imxrt_iomuxc.h"
#include "imxrt_gpio.h"
#include "chip/imxrt_daisy.h"

/****************************************************************************
 * Pre-processor Definitions
 ****************************************************************************/

#define IMXRT_PADMUX_INVALID    255

/****************************************************************************
 * Private Data
 ****************************************************************************/

static const uint8_t g_gpio1_padmux[IMXRT_GPIO_NPINS] = {
	IMXRT_PADMUX_GPIO_AD_B0_00_INDEX,	/* GPIO1 Pin 0 */
	IMXRT_PADMUX_GPIO_AD_B0_01_INDEX,	/* GPIO1 Pin 1 */
	IMXRT_PADMUX_GPIO_AD_B0_02_INDEX,	/* GPIO1 Pin 2 */
	IMXRT_PADMUX_GPIO_AD_B0_03_INDEX,	/* GPIO1 Pin 3 */
	IMXRT_PADMUX_GPIO_AD_B0_04_INDEX,	/* GPIO1 Pin 4 */
	IMXRT_PADMUX_GPIO_AD_B0_05_INDEX,	/* GPIO1 Pin 5 */
	IMXRT_PADMUX_GPIO_AD_B0_06_INDEX,	/* GPIO1 Pin 6 */
	IMXRT_PADMUX_GPIO_AD_B0_07_INDEX,	/* GPIO1 Pin 7 */

	IMXRT_PADMUX_GPIO_AD_B0_08_INDEX,	/* GPIO1 Pin 8 */
	IMXRT_PADMUX_GPIO_AD_B0_09_INDEX,	/* GPIO1 Pin 9 */
	IMXRT_PADMUX_GPIO_AD_B0_10_INDEX,	/* GPIO1 Pin 10 */
	IMXRT_PADMUX_GPIO_AD_B0_11_INDEX,	/* GPIO1 Pin 11 */
	IMXRT_PADMUX_GPIO_AD_B0_12_INDEX,	/* GPIO1 Pin 12 */
	IMXRT_PADMUX_GPIO_AD_B0_13_INDEX,	/* GPIO1 Pin 13 */
	IMXRT_PADMUX_GPIO_AD_B0_14_INDEX,	/* GPIO1 Pin 14 */
	IMXRT_PADMUX_GPIO_AD_B0_15_INDEX,	/* GPIO1 Pin 15 */

	IMXRT_PADMUX_GPIO_AD_B1_00_INDEX,	/* GPIO1 Pin 16 */
	IMXRT_PADMUX_GPIO_AD_B1_01_INDEX,	/* GPIO1 Pin 17 */
	IMXRT_PADMUX_GPIO_AD_B1_02_INDEX,	/* GPIO1 Pin 18 */
	IMXRT_PADMUX_GPIO_AD_B1_03_INDEX,	/* GPIO1 Pin 19 */
	IMXRT_PADMUX_GPIO_AD_B1_04_INDEX,	/* GPIO1 Pin 20 */
	IMXRT_PADMUX_GPIO_AD_B1_05_INDEX,	/* GPIO1 Pin 21 */
	IMXRT_PADMUX_GPIO_AD_B1_06_INDEX,	/* GPIO1 Pin 22 */
	IMXRT_PADMUX_GPIO_AD_B1_07_INDEX,	/* GPIO1 Pin 23 */

	IMXRT_PADMUX_GPIO_AD_B1_08_INDEX,	/* GPIO1 Pin 24 */
	IMXRT_PADMUX_GPIO_AD_B1_09_INDEX,	/* GPIO1 Pin 25 */
	IMXRT_PADMUX_GPIO_AD_B1_10_INDEX,	/* GPIO1 Pin 26 */
	IMXRT_PADMUX_GPIO_AD_B1_11_INDEX,	/* GPIO1 Pin 27 */
	IMXRT_PADMUX_GPIO_AD_B1_12_INDEX,	/* GPIO1 Pin 28 */
	IMXRT_PADMUX_GPIO_AD_B1_13_INDEX,	/* GPIO1 Pin 29 */
	IMXRT_PADMUX_GPIO_AD_B1_14_INDEX,	/* GPIO1 Pin 30 */
	IMXRT_PADMUX_GPIO_AD_B1_15_INDEX	/* GPIO1 Pin 31 */
};

#if defined(CONFIG_ARCH_CHIP_FAMILY_IMXRT105x)
static const uint8_t g_gpio2_padmux[IMXRT_GPIO_NPINS] = {
	IMXRT_PADMUX_GPIO_B0_00_INDEX,	/* GPIO2 Pin 0 */
	IMXRT_PADMUX_GPIO_B0_01_INDEX,	/* GPIO2 Pin 1 */
	IMXRT_PADMUX_GPIO_B0_02_INDEX,	/* GPIO2 Pin 2 */
	IMXRT_PADMUX_GPIO_B0_03_INDEX,	/* GPIO2 Pin 3 */
	IMXRT_PADMUX_GPIO_B0_04_INDEX,	/* GPIO2 Pin 4 */
	IMXRT_PADMUX_GPIO_B0_05_INDEX,	/* GPIO2 Pin 5 */
	IMXRT_PADMUX_GPIO_B0_06_INDEX,	/* GPIO2 Pin 6 */
	IMXRT_PADMUX_GPIO_B0_07_INDEX,	/* GPIO2 Pin 7 */

	IMXRT_PADMUX_GPIO_B0_08_INDEX,	/* GPIO2 Pin 8 */
	IMXRT_PADMUX_GPIO_B0_09_INDEX,	/* GPIO2 Pin 9 */
	IMXRT_PADMUX_GPIO_B0_10_INDEX,	/* GPIO2 Pin 10 */
	IMXRT_PADMUX_GPIO_B0_11_INDEX,	/* GPIO2 Pin 11 */
	IMXRT_PADMUX_GPIO_B0_12_INDEX,	/* GPIO2 Pin 12 */
	IMXRT_PADMUX_GPIO_B0_13_INDEX,	/* GPIO2 Pin 13 */
	IMXRT_PADMUX_GPIO_B0_14_INDEX,	/* GPIO2 Pin 14 */
	IMXRT_PADMUX_GPIO_B0_15_INDEX,	/* GPIO2 Pin 15 */

	IMXRT_PADMUX_GPIO_B1_00_INDEX,	/* GPIO2 Pin 16 */
	IMXRT_PADMUX_GPIO_B1_01_INDEX,	/* GPIO2 Pin 17 */
	IMXRT_PADMUX_GPIO_B1_02_INDEX,	/* GPIO2 Pin 18 */
	IMXRT_PADMUX_GPIO_B1_03_INDEX,	/* GPIO2 Pin 19 */
	IMXRT_PADMUX_GPIO_B1_04_INDEX,	/* GPIO2 Pin 20 */
	IMXRT_PADMUX_GPIO_B1_05_INDEX,	/* GPIO2 Pin 21 */
	IMXRT_PADMUX_GPIO_B1_06_INDEX,	/* GPIO2 Pin 22 */
	IMXRT_PADMUX_GPIO_B1_07_INDEX,	/* GPIO2 Pin 23 */

	IMXRT_PADMUX_GPIO_B1_08_INDEX,	/* GPIO2 Pin 24 */
	IMXRT_PADMUX_GPIO_B1_09_INDEX,	/* GPIO2 Pin 25 */
	IMXRT_PADMUX_GPIO_B1_10_INDEX,	/* GPIO2 Pin 26 */
	IMXRT_PADMUX_GPIO_B1_11_INDEX,	/* GPIO2 Pin 27 */
	IMXRT_PADMUX_GPIO_B1_12_INDEX,	/* GPIO2 Pin 28 */
	IMXRT_PADMUX_GPIO_B1_13_INDEX,	/* GPIO2 Pin 29 */
	IMXRT_PADMUX_GPIO_B1_14_INDEX,	/* GPIO2 Pin 30 */
	IMXRT_PADMUX_GPIO_B1_15_INDEX	/* GPIO2 Pin 31 */
};
#elif defined(CONFIG_ARCH_CHIP_FAMILY_IMXRT102x)
static const uint8_t g_gpio2_padmux[IMXRT_GPIO_NPINS] = {
	IMXRT_PADMUX_GPIO_EMC_00_INDEX,	/* GPIO2 Pin 0 */
	IMXRT_PADMUX_GPIO_EMC_01_INDEX,	/* GPIO2 Pin 1 */
	IMXRT_PADMUX_GPIO_EMC_02_INDEX,	/* GPIO2 Pin 2 */
	IMXRT_PADMUX_GPIO_EMC_03_INDEX,	/* GPIO2 Pin 3 */
	IMXRT_PADMUX_GPIO_EMC_04_INDEX,	/* GPIO2 Pin 4 */
	IMXRT_PADMUX_GPIO_EMC_05_INDEX,	/* GPIO2 Pin 5 */
	IMXRT_PADMUX_GPIO_EMC_06_INDEX,	/* GPIO2 Pin 6 */
	IMXRT_PADMUX_GPIO_EMC_07_INDEX,	/* GPIO2 Pin 7 */

	IMXRT_PADMUX_GPIO_EMC_08_INDEX,	/* GPIO2 Pin 8 */
	IMXRT_PADMUX_GPIO_EMC_09_INDEX,	/* GPIO2 Pin 9 */
	IMXRT_PADMUX_GPIO_EMC_10_INDEX,	/* GPIO2 Pin 10 */
	IMXRT_PADMUX_GPIO_EMC_11_INDEX,	/* GPIO2 Pin 11 */
	IMXRT_PADMUX_GPIO_EMC_12_INDEX,	/* GPIO2 Pin 12 */
	IMXRT_PADMUX_GPIO_EMC_13_INDEX,	/* GPIO2 Pin 13 */
	IMXRT_PADMUX_GPIO_EMC_14_INDEX,	/* GPIO2 Pin 14 */
	IMXRT_PADMUX_GPIO_EMC_15_INDEX,	/* GPIO2 Pin 15 */

	IMXRT_PADMUX_GPIO_EMC_16_INDEX,	/* GPIO2 Pin 16 */
	IMXRT_PADMUX_GPIO_EMC_17_INDEX,	/* GPIO2 Pin 17 */
	IMXRT_PADMUX_GPIO_EMC_18_INDEX,	/* GPIO2 Pin 18 */
	IMXRT_PADMUX_GPIO_EMC_19_INDEX,	/* GPIO2 Pin 19 */
	IMXRT_PADMUX_GPIO_EMC_20_INDEX,	/* GPIO2 Pin 20 */
	IMXRT_PADMUX_GPIO_EMC_21_INDEX,	/* GPIO2 Pin 21 */
	IMXRT_PADMUX_GPIO_EMC_22_INDEX,	/* GPIO2 Pin 22 */
	IMXRT_PADMUX_GPIO_EMC_23_INDEX,	/* GPIO2 Pin 23 */

	IMXRT_PADMUX_GPIO_EMC_24_INDEX,	/* GPIO2 Pin 24 */
	IMXRT_PADMUX_GPIO_EMC_25_INDEX,	/* GPIO2 Pin 25 */
	IMXRT_PADMUX_GPIO_EMC_26_INDEX,	/* GPIO2 Pin 26 */
	IMXRT_PADMUX_GPIO_EMC_27_INDEX,	/* GPIO2 Pin 27 */
	IMXRT_PADMUX_GPIO_EMC_28_INDEX,	/* GPIO2 Pin 28 */
	IMXRT_PADMUX_GPIO_EMC_29_INDEX,	/* GPIO2 Pin 29 */
	IMXRT_PADMUX_GPIO_EMC_30_INDEX,	/* GPIO2 Pin 30 */
	IMXRT_PADMUX_GPIO_EMC_31_INDEX	/* GPIO2 Pin 31 */
};
#else
#error "i.MXRT check definition"
#endif

#if defined(CONFIG_ARCH_CHIP_FAMILY_IMXRT105x)
static const uint8_t g_gpio3_padmux[IMXRT_GPIO_NPINS] = {
	IMXRT_PADMUX_GPIO_SD_B1_00_INDEX,	/* GPIO3 Pin 0 */
	IMXRT_PADMUX_GPIO_SD_B1_01_INDEX,	/* GPIO3 Pin 1 */
	IMXRT_PADMUX_GPIO_SD_B1_02_INDEX,	/* GPIO3 Pin 2 */
	IMXRT_PADMUX_GPIO_SD_B1_03_INDEX,	/* GPIO3 Pin 3 */
	IMXRT_PADMUX_GPIO_SD_B1_04_INDEX,	/* GPIO3 Pin 4 */
	IMXRT_PADMUX_GPIO_SD_B1_05_INDEX,	/* GPIO3 Pin 5 */
	IMXRT_PADMUX_GPIO_SD_B1_06_INDEX,	/* GPIO3 Pin 6 */
	IMXRT_PADMUX_GPIO_SD_B1_07_INDEX,	/* GPIO3 Pin 7 */

	IMXRT_PADMUX_GPIO_SD_B1_08_INDEX,	/* GPIO3 Pin 8 */
	IMXRT_PADMUX_GPIO_SD_B1_09_INDEX,	/* GPIO3 Pin 9 */
	IMXRT_PADMUX_GPIO_SD_B1_10_INDEX,	/* GPIO3 Pin 10 */
	IMXRT_PADMUX_GPIO_SD_B1_11_INDEX,	/* GPIO3 Pin 11 */
	IMXRT_PADMUX_GPIO_SD_B0_00_INDEX,	/* GPIO3 Pin 12 */
	IMXRT_PADMUX_GPIO_SD_B0_01_INDEX,	/* GPIO3 Pin 13 */
	IMXRT_PADMUX_GPIO_SD_B0_02_INDEX,	/* GPIO3 Pin 14 */
	IMXRT_PADMUX_GPIO_SD_B0_03_INDEX,	/* GPIO3 Pin 15 */

	IMXRT_PADMUX_GPIO_SD_B0_04_INDEX,	/* GPIO3 Pin 16 */
	IMXRT_PADMUX_GPIO_SD_B0_05_INDEX,	/* GPIO3 Pin 17 */
	IMXRT_PADMUX_GPIO_EMC_32_INDEX,	/* GPIO3 Pin 18 */
	IMXRT_PADMUX_GPIO_EMC_33_INDEX,	/* GPIO3 Pin 19 */
	IMXRT_PADMUX_GPIO_EMC_34_INDEX,	/* GPIO3 Pin 20 */
	IMXRT_PADMUX_GPIO_EMC_35_INDEX,	/* GPIO3 Pin 21 */
	IMXRT_PADMUX_GPIO_EMC_36_INDEX,	/* GPIO3 Pin 22 */
	IMXRT_PADMUX_GPIO_EMC_37_INDEX,	/* GPIO3 Pin 23 */

	IMXRT_PADMUX_GPIO_EMC_38_INDEX,	/* GPIO3 Pin 24 */
	IMXRT_PADMUX_GPIO_EMC_39_INDEX,	/* GPIO3 Pin 25 */
	IMXRT_PADMUX_GPIO_EMC_40_INDEX,	/* GPIO3 Pin 26 */
	IMXRT_PADMUX_GPIO_EMC_41_INDEX,	/* GPIO3 Pin 27 */
	IMXRT_PADMUX_INVALID,		/* GPIO3 Pin 28 */
	IMXRT_PADMUX_INVALID,		/* GPIO3 Pin 29 */
	IMXRT_PADMUX_INVALID,		/* GPIO3 Pin 30 */
	IMXRT_PADMUX_INVALID		/* GPIO3 Pin 31 */
};

static const uint8_t g_gpio4_padmux[IMXRT_GPIO_NPINS] = {
	IMXRT_PADMUX_GPIO_EMC_00_INDEX,	/* GPIO4 Pin 0 */
	IMXRT_PADMUX_GPIO_EMC_01_INDEX,	/* GPIO4 Pin 1 */
	IMXRT_PADMUX_GPIO_EMC_02_INDEX,	/* GPIO4 Pin 2 */
	IMXRT_PADMUX_GPIO_EMC_03_INDEX,	/* GPIO4 Pin 3 */
	IMXRT_PADMUX_GPIO_EMC_04_INDEX,	/* GPIO4 Pin 4 */
	IMXRT_PADMUX_GPIO_EMC_05_INDEX,	/* GPIO4 Pin 5 */
	IMXRT_PADMUX_GPIO_EMC_06_INDEX,	/* GPIO4 Pin 6 */
	IMXRT_PADMUX_GPIO_EMC_07_INDEX,	/* GPIO4 Pin 7 */

	IMXRT_PADMUX_GPIO_EMC_08_INDEX,	/* GPIO4 Pin 8 */
	IMXRT_PADMUX_GPIO_EMC_09_INDEX,	/* GPIO4 Pin 9 */
	IMXRT_PADMUX_GPIO_EMC_10_INDEX,	/* GPIO4 Pin 10 */
	IMXRT_PADMUX_GPIO_EMC_11_INDEX,	/* GPIO4 Pin 11 */
	IMXRT_PADMUX_GPIO_EMC_12_INDEX,	/* GPIO4 Pin 12 */
	IMXRT_PADMUX_GPIO_EMC_13_INDEX,	/* GPIO4 Pin 13 */
	IMXRT_PADMUX_GPIO_EMC_14_INDEX,	/* GPIO4 Pin 14 */
	IMXRT_PADMUX_GPIO_EMC_15_INDEX,	/* GPIO4 Pin 15 */

	IMXRT_PADMUX_GPIO_EMC_16_INDEX,	/* GPIO4 Pin 16 */
	IMXRT_PADMUX_GPIO_EMC_17_INDEX,	/* GPIO4 Pin 17 */
	IMXRT_PADMUX_GPIO_EMC_18_INDEX,	/* GPIO4 Pin 18 */
	IMXRT_PADMUX_GPIO_EMC_19_INDEX,	/* GPIO4 Pin 19 */
	IMXRT_PADMUX_GPIO_EMC_20_INDEX,	/* GPIO4 Pin 20 */
	IMXRT_PADMUX_GPIO_EMC_21_INDEX,	/* GPIO4 Pin 21 */
	IMXRT_PADMUX_GPIO_EMC_22_INDEX,	/* GPIO4 Pin 22 */
	IMXRT_PADMUX_GPIO_EMC_23_INDEX,	/* GPIO4 Pin 23 */

	IMXRT_PADMUX_GPIO_EMC_24_INDEX,	/* GPIO4 Pin 24 */
	IMXRT_PADMUX_GPIO_EMC_25_INDEX,	/* GPIO4 Pin 25 */
	IMXRT_PADMUX_GPIO_EMC_26_INDEX,	/* GPIO4 Pin 26 */
	IMXRT_PADMUX_GPIO_EMC_27_INDEX,	/* GPIO4 Pin 27 */
	IMXRT_PADMUX_GPIO_EMC_28_INDEX,	/* GPIO4 Pin 28 */
	IMXRT_PADMUX_GPIO_EMC_29_INDEX,	/* GPIO4 Pin 29 */
	IMXRT_PADMUX_GPIO_EMC_30_INDEX,	/* GPIO4 Pin 30 */
	IMXRT_PADMUX_GPIO_EMC_31_INDEX	/* GPIO4 Pin 31 */
};

static const uint8_t g_gpio5_padmux[IMXRT_GPIO_NPINS] = {
	IMXRT_PADMUX_WAKEUP_INDEX,	/* GPIO5 Pin 0 */
	IMXRT_PADMUX_PMIC_ON_REQ_INDEX,	/* GPIO5 Pin 1 */
	IMXRT_PADMUX_PMIC_STBY_REQ_INDEX,	/* GPIO5 Pin 2 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 3 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 4 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 5 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 6 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 7 */

	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 8 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 9 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 10 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 11 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 12 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 13 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 14 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 15 */

	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 16 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 17 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 18 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 19 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 20 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 21 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 22 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 23 */

	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 24 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 25 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 26 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 27 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 28 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 29 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 30 */
	IMXRT_PADMUX_INVALID		/* GPIO5 Pin 31 */
};
#elif defined(CONFIG_ARCH_CHIP_FAMILY_IMXRT102x)
static const uint8_t g_gpio3_padmux[IMXRT_GPIO_NPINS] = {
	IMXRT_PADMUX_GPIO_EMC_32_INDEX,	/* GPIO3 Pin 0 */
	IMXRT_PADMUX_GPIO_EMC_33_INDEX,	/* GPIO3 Pin 1 */
	IMXRT_PADMUX_GPIO_EMC_34_INDEX,	/* GPIO3 Pin 2 */
	IMXRT_PADMUX_GPIO_EMC_35_INDEX,	/* GPIO3 Pin 3 */
	IMXRT_PADMUX_GPIO_EMC_36_INDEX,	/* GPIO3 Pin 4 */
	IMXRT_PADMUX_GPIO_EMC_37_INDEX,	/* GPIO3 Pin 5 */
	IMXRT_PADMUX_GPIO_EMC_38_INDEX,	/* GPIO3 Pin 6 */
	IMXRT_PADMUX_GPIO_EMC_39_INDEX,	/* GPIO3 Pin 7 */

	IMXRT_PADMUX_GPIO_EMC_40_INDEX,	/* GPIO3 Pin 8 */
	IMXRT_PADMUX_GPIO_EMC_41_INDEX,	/* GPIO3 Pin 9 */
	IMXRT_PADMUX_INVALID,	/* GPIO3 Pin 10 */
	IMXRT_PADMUX_INVALID,	/* GPIO3 Pin 11 */
	IMXRT_PADMUX_INVALID,	/* GPIO3 Pin 12 */
	IMXRT_PADMUX_GPIO_SD_B0_00_INDEX,	/* GPIO3 Pin 13 */
	IMXRT_PADMUX_GPIO_SD_B0_01_INDEX,	/* GPIO3 Pin 14 */
	IMXRT_PADMUX_GPIO_SD_B0_02_INDEX,	/* GPIO3 Pin 15 */

	IMXRT_PADMUX_GPIO_SD_B0_03_INDEX,	/* GPIO3 Pin 16 */
	IMXRT_PADMUX_GPIO_SD_B0_04_INDEX,	/* GPIO3 Pin 17 */
	IMXRT_PADMUX_GPIO_SD_B0_05_INDEX,	/* GPIO3 Pin 18 */
	IMXRT_PADMUX_GPIO_SD_B0_06_INDEX,	/* GPIO3 Pin 19 */
	IMXRT_PADMUX_GPIO_SD_B1_00_INDEX,	/* GPIO3 Pin 20 */
	IMXRT_PADMUX_GPIO_SD_B1_01_INDEX,	/* GPIO3 Pin 21 */
	IMXRT_PADMUX_GPIO_SD_B1_02_INDEX,	/* GPIO3 Pin 22 */
	IMXRT_PADMUX_GPIO_SD_B1_03_INDEX,	/* GPIO3 Pin 23 */

	IMXRT_PADMUX_GPIO_SD_B1_04_INDEX,	/* GPIO3 Pin 24 */
	IMXRT_PADMUX_GPIO_SD_B1_05_INDEX,	/* GPIO3 Pin 25 */
	IMXRT_PADMUX_GPIO_SD_B1_06_INDEX,	/* GPIO3 Pin 26 */
	IMXRT_PADMUX_GPIO_SD_B1_07_INDEX,	/* GPIO3 Pin 27 */
	IMXRT_PADMUX_GPIO_SD_B1_08_INDEX,		/* GPIO3 Pin 28 */
	IMXRT_PADMUX_GPIO_SD_B1_09_INDEX,		/* GPIO3 Pin 29 */
	IMXRT_PADMUX_GPIO_SD_B1_10_INDEX,		/* GPIO3 Pin 30 */
	IMXRT_PADMUX_GPIO_SD_B1_11_INDEX		/* GPIO3 Pin 31 */
};

static const uint8_t g_gpio4_padmux[IMXRT_GPIO_NPINS] = {
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 0 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 1 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 2 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 3 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 4 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 5 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 6 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 7 */

	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 8 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 9 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 10 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 11 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 12 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 13 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 14 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 15 */

	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 16 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 17 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 18 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 19 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 20 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 21 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 22 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 23 */

	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 24 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 25 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 26 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 27 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 28 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 29 */
	IMXRT_PADMUX_INVALID,	/* GPIO4 Pin 30 */
	IMXRT_PADMUX_INVALID	/* GPIO4 Pin 31 */
};
static const uint8_t g_gpio5_padmux[IMXRT_GPIO_NPINS] = {
	IMXRT_PADMUX_WAKEUP_INDEX,	/* GPIO5 Pin 0 */
	IMXRT_PADMUX_PMIC_ON_REQ_INDEX,	/* GPIO5 Pin 1 */
	IMXRT_PADMUX_PMIC_STBY_REQ_INDEX,	/* GPIO5 Pin 2 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 3 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 4 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 5 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 6 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 7 */

	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 8 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 9 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 10 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 11 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 12 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 13 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 14 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 15 */

	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 16 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 17 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 18 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 19 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 20 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 21 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 22 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 23 */

	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 24 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 25 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 26 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 27 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 28 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 29 */
	IMXRT_PADMUX_INVALID,		/* GPIO5 Pin 30 */
	IMXRT_PADMUX_INVALID		/* GPIO5 Pin 31 */
};

#else
#error "i.MXRT check definition"
#endif

static FAR const uint8_t *g_gpio_padmux[IMXRT_GPIO_NPORTS + 1] = {
	g_gpio1_padmux,				/* GPIO1 */
	g_gpio2_padmux,				/* GPIO2 */
	g_gpio3_padmux,				/* GPIO3 */
	g_gpio4_padmux,				/* GPIO4 */
	g_gpio5_padmux,				/* GPIO5 */
#if IMXRT_GPIO_NPORTS > 5
	g_gpio1_padmux,                             /* GPIO6 */
	g_gpio2_padmux,                             /* GPIO7 */
	g_gpio3_padmux,                             /* GPIO8 */
	#if !defined(CONFIG_ARCH_CHIP_FAMILY_IMXRT102x)
	g_gpio4_padmux,                             /* GPIO9 */
	#endif
#endif
	NULL						/* End of list */
};

/************************************************************************************
 * Public Data
 ************************************************************************************/

/* Look-up table that maps GPIO1..GPIO5 indexes into GPIO register base addresses */

uintptr_t g_gpio_base[IMXRT_GPIO_NPORTS] = {
	IMXRT_GPIO1_BASE
#if IMXRT_GPIO_NPORTS > 1
	, IMXRT_GPIO2_BASE
#endif
#if IMXRT_GPIO_NPORTS > 2
	, IMXRT_GPIO3_BASE
#endif
#if !defined(CONFIG_ARCH_CHIP_FAMILY_IMXRT102x)
#if IMXRT_GPIO_NPORTS > 3
	, IMXRT_GPIO4_BASE
#endif
#endif
#if IMXRT_GPIO_NPORTS > 4
	, IMXRT_GPIO5_BASE
#endif
#if IMXRT_GPIO_NPORTS > 5
	, IMXRT_GPIO6_BASE
#endif
#if IMXRT_GPIO_NPORTS > 6
	, IMXRT_GPIO7_BASE
#endif
#if IMXRT_GPIO_NPORTS > 7
	, IMXRT_GPIO8_BASE
#endif
#if IMXRT_GPIO_NPORTS > 8
	, IMXRT_GPIO9_BASE
#endif
};

/****************************************************************************
 * Private Functions
 ****************************************************************************/

/****************************************************************************
 * Name: imxrt_padmux_address
 ****************************************************************************/

//static
uintptr_t imxrt_padmux_address(unsigned int index)
{
#if defined(IMXRT_PAD1MUX_OFFSET)
	if (index >= IMXRT_PADMUX_GPIO_SPI_B0_00_INDEX) {
		return (IMXRT_PAD1MUX_OFFSET(index - IMXRT_PADMUX_GPIO_SPI_B0_00_INDEX));
	}
#endif
	if (index >= IMXRT_PADMUX_WAKEUP_INDEX) {
		return (IMXRT_PADMUX_ADDRESS_SNVS(index - IMXRT_PADMUX_WAKEUP_INDEX));
	}

	return (IMXRT_PADMUX_ADDRESS(index));
}

/****************************************************************************
 * Name: imxrt_padctl_address
 ****************************************************************************/
//static
uintptr_t imxrt_padctl_address(unsigned int index)
{
#if defined(IMXRT_PAD1CTL_OFFSET)
	if (index >= IMXRT_PADCTL_GPIO_SPI_B0_00_INDEX) {
		return (IMXRT_PAD1CTL_OFFSET(index - IMXRT_PADCTL_GPIO_SPI_B0_00_INDEX));
	}
#endif
	if (index >= IMXRT_PADCTL_WAKEUP_INDEX) {
		return (IMXRT_PADCTL_ADDRESS_SNVS(index - IMXRT_PADCTL_WAKEUP_INDEX));
	}

	return (IMXRT_PADCTL_ADDRESS(index));
}

/****************************************************************************
 * Name: imxrt_gpio_dirout
 ****************************************************************************/

static inline void imxrt_gpio_dirout(int port, int pin)
{
	uint32_t regval = getreg32(IMXRT_GPIO_GDIR(port));
	regval |= GPIO_PIN(pin);
	putreg32(regval, IMXRT_GPIO_GDIR(port));
}

/****************************************************************************
 * Name: imxrt_gpio_dirin
 ****************************************************************************/

static inline void imxrt_gpio_dirin(int port, int pin)
{
	uint32_t regval = getreg32(IMXRT_GPIO_GDIR(port));
	regval &= ~GPIO_PIN(pin);
	putreg32(regval, IMXRT_GPIO_GDIR(port));
}

/****************************************************************************
 * Name: imxrt_gpio_setoutput
 ****************************************************************************/

static void imxrt_gpio_setoutput(int port, int pin, bool value)
{
	uintptr_t regaddr = IMXRT_GPIO_DR(port);
	uint32_t regval;

	regval = getreg32(regaddr);
	if (value) {
		regval |= GPIO_PIN(pin);
	} else {
		regval &= ~GPIO_PIN(pin);
	}

	putreg32(regval, regaddr);
}

/****************************************************************************
 * Name: imxrt_gpio_getinput
 ****************************************************************************/

static inline bool imxrt_gpio_getinput(int port, int pin)
{
	uintptr_t regaddr = IMXRT_GPIO_DR(port);
	uint32_t regval;

	regval = getreg32(regaddr);
	return ((regval & GPIO_PIN(pin)) != 0);
}

/****************************************************************************
 * Name: imxrt_gpio_select
 * GPIO{1234}(l) and GPIO{6789}(h) share same IO MUX function, GPIO_MUXn
 * selects one GPIO function.
 * 0: GPIOl[n] is selected
 * 1: GPIOh[n] is selected
 ****************************************************************************/

static inline int imxrt_gpio_select(int port, int pin)
{
#if IMXRT_GPIO_NPORTS > 5
	uint32_t gpr = port;
	uint32_t setbits = 1 << pin;
	uint32_t clearbits = 1 << pin;
	uintptr_t regaddr = (uintptr_t)IMXRT_IOMUXC_GPR_GPR26;

	if (port != GPIO5) {
		/* Uses GPR26 as the base */

		if (port >= GPIO6) {
			/* Map port to correct gpr index and set the GPIO_MUX3_GPIO[b]_SEL
			* bit
			*/

			gpr = port - GPIO6;
			clearbits = 0;
		} else {
			/* The port is correct gpr index, so just clear the
			* GPIO_MUX3_GPIO[b]_SEL bit.
			*/

			setbits = 0;
		}

		regaddr |= gpr * sizeof(uint32_t);
		modifyreg32(regaddr, clearbits, setbits);
	}
#endif
	return OK;
}

/****************************************************************************
 * Name: imxrt_gpio_configinput
 ****************************************************************************/

static int imxrt_gpio_configinput(gpio_pinset_t pinset)
{
	int port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
	int pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
	FAR const uint8_t *table;
	iomux_pinset_t ioset;
	uintptr_t regaddr;
	unsigned int index;

	DEBUGASSERT((unsigned int)port < IMXRT_GPIO_NPORTS);

	/* Configure pin as in input */

	imxrt_gpio_dirin(port, pin);

	/* Configure pin as a GPIO */

	table = g_gpio_padmux[port];
	if (table == NULL) {
		return -EINVAL;
	}

	index = (unsigned int)table[pin];
	if (index >= IMXRT_PADMUX_NREGISTERS) {
		return -EINVAL;
	}

	regaddr = imxrt_padmux_address(index);
	putreg32(PADMUX_MUXMODE_ALT5, regaddr);

	imxrt_gpio_select(port, pin);
	/* Configure pin pad settings */

	index = imxrt_padmux_map(index);
	if (index >= IMXRT_PADCTL_NREGISTERS) {
		return -EINVAL;
	}

	regaddr = imxrt_padctl_address(index);
	ioset = (iomux_pinset_t)((pinset & GPIO_IOMUX_MASK) >> GPIO_IOMUX_SHIFT);
	return imxrt_iomux_configure(regaddr, ioset);
}

/****************************************************************************
 * Name: imxrt_gpio_configoutput
 ****************************************************************************/

static inline int imxrt_gpio_configoutput(gpio_pinset_t pinset)
{
	int port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
	int pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
	bool value = ((pinset & GPIO_OUTPUT_ONE) != 0);

	DEBUGASSERT((unsigned int)port < IMXRT_GPIO_NPORTS);

	/* Set the output value */

	imxrt_gpio_setoutput(port, pin, value);

	/* Convert the configured input GPIO to an output */

	imxrt_gpio_dirout(port, pin);
	return OK;
}

/****************************************************************************
 * Name: imxrt_gpio_configperiph
 ****************************************************************************/

static inline int imxrt_gpio_configperiph(gpio_pinset_t pinset)
{
	iomux_pinset_t ioset;
	uintptr_t regaddr;
	uint32_t regval;
	uint32_t alt;
	unsigned int index;

	/* Configure pin as a peripheral via SW MUX Control Register */

	index   = ((pinset & GPIO_PADMUX_MASK) >> GPIO_PADMUX_SHIFT);
	regaddr = imxrt_padmux_address(index);

	alt     = (pinset & GPIO_ALT_MASK) >> GPIO_ALT_SHIFT;
	regval  = alt << PADMUX_MUXMODE_SHIFT;
	regval |= (pinset & GPIO_SION_MASK) ? PADMUX_SION : 0;

	putreg32(regval, regaddr);

	/* Configure pin Daisy Select Input Daisy Register */

	imxrt_daisy_select(index, alt);

	/* Configure pin pad settings SW PAD Control Register*/

	index = imxrt_padmux_map(index);
	if (index >= IMXRT_PADCTL_NREGISTERS) {
		return -EINVAL;
	}

	regaddr = imxrt_padctl_address(index);
	ioset   = (iomux_pinset_t)((pinset & GPIO_IOMUX_MASK) >> GPIO_IOMUX_SHIFT);
	return imxrt_iomux_configure(regaddr, ioset);
}

/****************************************************************************
 * Public Functions
 ****************************************************************************/
uint16_t imxrt_gpio_irqvector(uint32_t pinset)
{
	int port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
	int pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
	uint16_t ret = 0;

	switch (port) {
	case GPIO1INDEX:
		if (pin > 15) {
			ret = _IMXRT_GPIO1_16_31_BASE + (pin - 16);
		} else {
			ret = _IMXRT_GPIO1_0_15_BASE + pin;
		}
		break;
	case GPIO2INDEX:
		if (pin > 15) {
			ret = _IMXRT_GPIO2_16_31_BASE + (pin - 16);
		} else {
			ret = _IMXRT_GPIO2_0_15_BASE + pin;
		}
		break;
	case GPIO3INDEX:
		if (pin > 15) {
			ret = _IMXRT_GPIO3_16_31_BASE + (pin - 16);
		} else {
			ret = _IMXRT_GPIO3_0_15_BASE + pin;
		}
		break;
	case GPIO4INDEX:
		if (pin > 15) {
			ret = _IMXRT_GPIO4_16_31_BASE + (pin - 16);
		} else {
			ret = _IMXRT_GPIO4_0_15_BASE + pin;
		}
		break;
	case GPIO5INDEX:
		if (pin > 15) {
			ret = _IMXRT_GPIO5_16_31_BASE + (pin - 16);
		} else {
			ret = _IMXRT_GPIO5_0_15_BASE + pin;
		}
		break;
	default:
		break;
	}
	return ret;
}

/****************************************************************************
 * Name: imxrt_config_gpio
 *
 * Description:
 *   Configure a GPIO pin based on pin-encoded description of the pin.
 *
 ****************************************************************************/

int imxrt_config_gpio(gpio_pinset_t pinset)
{
	irqstate_t flags;
	int ret;

	/* Configure the pin as an input initially to avoid any spurious outputs */

	flags = irqsave();

	/* Configure based upon the pin mode */

	switch (pinset & GPIO_MODE_MASK) {
	case GPIO_INPUT: {
		/* Configure the pin as a GPIO input */
#ifdef CONFIG_IMXRT_ADC
		if ((pinset & IOMUX_PULL_MASK) == IOMUX_PULL_KEEP) {
			ret = imxrt_adc_configinput(pinset);			// confirm �ʿ�
		} else
#endif
			ret = imxrt_gpio_configinput(pinset);
	}
	break;

	case GPIO_OUTPUT: {
		/* First configure the pin as a GPIO input to avoid output
			* glitches.
			*/

		ret = imxrt_gpio_configinput(pinset);
		if (ret >= 0) {
			/* Convert the input to an output */

			ret = imxrt_gpio_configoutput(pinset);
		}
	}
	break;

	case GPIO_PERIPH: {
		/* Configure the pin as a peripheral */

		ret = imxrt_gpio_configperiph(pinset);
	}
	break;

#ifdef CONFIG_IMXRT_GPIO_IRQ
	case GPIO_INTERRUPT: {
		/* Configure the pin as a GPIO input */

		ret = imxrt_gpio_configinput(pinset);
		if (ret == OK) {
			ret = imxrt_gpioirq_configure(pinset);
		}
	}
	break;
#endif

	default:
		ret = -EINVAL;
		break;
	}

	irqrestore(flags);
	return ret;
}

/************************************************************************************
 * Name: imxrt_gpio_write
 *
 * Description:
 *   Write one or zero to the selected GPIO pin
 *
 ************************************************************************************/

void imxrt_gpio_write(gpio_pinset_t pinset, bool value)
{
	irqstate_t flags;
	int port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
	int pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;

	DEBUGASSERT((unsigned int)port < IMXRT_GPIO_NPORTS);

	flags = irqsave();
	imxrt_gpio_setoutput(port, pin, value);
	irqrestore(flags);
}

/************************************************************************************
 * Name: imxrt_gpio_read
 *
 * Description:
 *   Read one or zero from the selected GPIO pin
 *
 ************************************************************************************/

bool imxrt_gpio_read(gpio_pinset_t pinset)
{
	irqstate_t flags;
	int port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
	int pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
	bool value;

	DEBUGASSERT((unsigned int)port < IMXRT_GPIO_NPORTS);

	flags = irqsave();
	value = imxrt_gpio_getinput(port, pin);
	irqrestore(flags);
	return value;
}
